package com.zhouheng.common.base.enums;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumValue.Validator.class)
public @interface EnumValue {

    String message() default "枚举值错误";

    Class<? extends BaseEnum> enumType();

    boolean nullable() default false;

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    CheckType checkType() default CheckType.ByValue;

    class Validator implements ConstraintValidator<EnumValue, Object> {
        private Class<? extends BaseEnum> enumType;
        private boolean nullable;
        private CheckType checkType;

        @Override
        public void initialize(EnumValue enumValue) {
            enumType = enumValue.enumType();
            nullable = enumValue.nullable();
            checkType = enumValue.checkType();
        }

        @Override
        public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
            if (nullable && value == null) {
                return Boolean.TRUE;
            }

            return value != null && isEnum(value);
        }

        private boolean isEnum(Object value) {
            if (checkType == CheckType.ByName) {
                return BaseEnum.nameOf(enumType, value.toString()).isPresent();
            }

            return BaseEnum.valueOf(enumType, value).isPresent();
        }
    }

    enum CheckType {
        ByName, ByValue;
    }
}
